[Previous] [Next]

The CommonDialog Control

The CommonDialog control provides an easy and convenient way to invoke the Color, Font, Printer, FileOpen, and FileSave Windows common dialog boxes, and it also allows you to display a page in a help file. This control exposes only properties and methods—no events. In most cases, you don't set any properties at design time because it's often preferable to assign all of them at run time, especially when you use the same control to display different dialog boxes. The control is invisible during the execution, so it doesn't support properties such as Left, Visible, or TabIndex. This control is embedded in the ComDlg32.ocx file, which has to be distributed with any Visual Basic application that uses it.

The lack of a visible interface and the lack of events doesn't mean that this control is easy to use, though. As a matter of fact, using the CommonDialog control is a complex enterprise because it supports many options, some of which aren't always intuitive. Some properties have different meanings, depending on which common dialog box you're displaying. For example, the Flags property is a bit-field property, and the meaning of each bit is different for each of the various common dialog boxes.

One of the few properties that can have the same meaning regardless of which common dialog box you're displaying is CancelError. If this property is True, an end user closing the dialog box using the Cancel key causes error 32755 (equal to the constant cdlCancel) to be raised in the calling program. The CommonDialog control includes intrinsic constants for all the errors that can be generated at run time.

All common dialog boxes also share a few properties related to help support. You can display a Help button in the common dialog box and tell the CommonDialog control what page in what help file must be displayed when the user clicks the Help button. HelpFile is the complete name of the help file, HelpContext is the context ID of the requested page, and HelpCommand is the action that must be performed when the button is clicked. (It's usually assigned the value 1-cdlHelpContext.) Don't forget that to actually display the Help button, you must set a bit in the Flags property. The position of this bit varies with the particular common dialog box, for example:

' Show a Help button. 
CommonDialog1.HelpFile = "F:\vbprogs\DlgMaste\Tdm.hlp"
CommonDialog1.HelpContext = 12
CommonDialog1.HelpCommand = cdlHelpContext
' The value for the Flags property depends on the dialog.
If ShowColorDialog Then
    CommonDialog1.Flags = cdlCCHelpButton
    CommonDialog1.ShowColor
ElseIf ShowFontDialog Then
    CommonDialog1.Flags = cdlCFHelpButton
    CommonDialog1.ShowFont
Else
    ' And so on
End If

For more information about help properties, see the section "Help Windows," later in this chapter.

The CommonDialog control exposes six methods: ShowColor, ShowFont, ShowPrinter, ShowOpen, ShowSave, and ShowHelp. Each method displays a different common dialog box, as explained in the following sections. On the companion CD, you'll find a complete demonstration program (part of which is visible in Figure 122) that shows in action all the common dialog boxes described in this section.

The Color Dialog

The Color common dialog box lets users select a color. It also permits them to define new custom colors, but you can keep this privilege from users by assigning the 4cdlCCPreventFullOpen value to the Flags property. Alternatively, you can display the custom color section of the dialog box when the dialog appears by setting the 2cdlCCFullOpen bit. (Custom color choices take up the right half of the dialog box shown in Figure 12-2.) You can initially highlight a color in the dialog box by assigning its RGB value to the Color property and setting the 1-cdlCCRGBInit bit in the Flags property, as in the following example:

' Let the user change the ForeColor of the Text1 control.
With CommonDialog1
    ' Prevent display of the custom color section
    ' of the dialog.
    .Flags = cdlCCPreventFullOpen Or cdlCCRGBInit 
    .Color = Text1.ForeColor
        .CancelError = False
        .ShowColor
        Text1.ForeColor = .Color
End With

When you provide an initial color, you don't need to set the CancelError property to True; if the user clicks on the Cancel key, the value of the Color property doesn't change.

Click to view at full size.

Figure 12-2. The Color common dialog box, with the section for creating custom colors already opened, as it appears in the demonstration program.

The Font Dialog

The Font dialog box lets users select font names and attributes. You can initialize the value shown in the dialog box, and you can decide which attributes can be modified. Of course, it's also up to you to apply the new attributes to controls and objects in your application. An example of a Font dialog box, with all the options enabled, is shown in Figure 12-3.

Figure 12-3. The Font common dialog box.

The font attributes can be initialized (and retrieved when the user closes the dialog box) through a number of properties whose names are self-explanatory: FontName, FontSize, FontBold, FontItalic, FontUnderLine, FontStrikeThru, and Color.

When used with the Font common dialog box, the Flags property accepts all the options that are summarized in Table 12-2. You use these flags to affect what fonts are listed in the dialog box and to restrict user selection. One of the bits that you should always include is cdlCFForceFontExist. Besides, at least one of the first four values in Table 12-2 must be specified; otherwise, the CommonDialog control raises an error 24574 "No fonts exist."

Table 12-2. Values for the Flags property for a Font common dialog box.

Constant Description
cdlCFScreenFonts Show screen fonts.
cdlCFPrinterFonts Show printer fonts.
cdlCFBoth Show both screen fonts and printer fonts. (This is the sum of cdlCFScreenFonts and cdlCFPrinterFonts.)
cdlCFWYSIWYG Show only fonts that are available both on the screen and on the printer.
cdlCFANSIOnly Restrict selection to fonts that use ANSI character sets.
cdlCFFixedPitchOnly Restrict selection to nonproportional (fixed pitch) fonts.
cdlCFNoVectorFonts Restrict selection to nonvector fonts.
cdlCFScalableOnly Restrict selection to scalable fonts.
cdlCFTTOnly Restrict selection to TrueType fonts.
cdlCFNoSimulations Restrict selection to fonts that aren't GDI font simulations.
cdlCFLimitSize Restrict selection to font size in the range indicated by the Min and Max properties.
cdlCFForceFontExist Raise an error if user selects a font or a style that doesn't exist.
cdlCFEffects Enable the strikethrough, underline, and color fields in the dialog box.
cdlCFNoFaceSel Don't select font name.
cdlCFNoSizeSel Don't select font size.
cdlCFNoStyleSel Don't select font style. (Can be tested on exit to determine whether user selected a style.)
cdlCFHelpButton Display the Help button.

The following piece of code lets the user modify the font attributes of a TextBox control. It limits the user's selection to existing screen fonts and forces the font size in the range from 8 to 80 points:

With CommonDialog1
    .Flags = cdlCFScreenFonts Or cdlCFForceFontExist Or cdlCFEffects _
        Or cdlCFLimitSize
    .Min = 8
    .Max = 80
    .FontName = Text1.FontName
    .FontSize = Text1.FontSize
    .FontBold = Text1.FontBold
    .FontItalic = Text1.FontItalic
    .FontUnderline = Text1.FontUnderline
    .FontStrikethru = Text1.FontStrikethru
    .CancelError = False
    .ShowFont
    Text1.FontName = .FontName
    Text1.FontBold = .FontBold
    Text1.FontItalic = .FontItalic
    Text1.FontSize = .FontSize
    Text1.FontUnderline = .FontUnderline
    Text1.FontStrikethru = .FontStrikethru
End With

In this particular case, you don't need to set the CancelError property to True because if the user clicks on the Cancel button the control doesn't modify any Fontxxxx properties and all Fontxxxx property values can be assigned back to the control without any undesirable effects.

When you don't want to initialize a field with a well-defined value, you have a more complex problem. Consider this situation: You're writing a word processor application, and you display a Font common dialog box to let the user select the font name, size, and attributes of the selection portion of text. If the selection contains characters with homogeneous attributes, you can (and should) initialize the corresponding fields in the common dialog box. On the other hand, if the selection includes characters of different fonts or with different sizes or attributes, you should leave these fields blank. You can do this by specifying the cdlCFNoFaceSel, cdlCFNoStyleSel, and cdlCFNoStyleSel bits of the Flags property. The following code lets the user modify the attributes of a RichTextBox control. (I describe this control in depth later in this chapter.)

On Error Resume Next
With CommonDialog1
    .Flags = cdlCFBoth Or cdlCFForceFontExist Or cdlCFEffects
    If IsNull(RichTextBox1.SelFontName) Then
        .Flags = .Flags Or cdlCFNoFaceSel
    Else
        .FontName = RichTextBox1.SelFontName
    End If
    If IsNull(RichTextBox1.SelFontSize) Then
        .Flags = .Flags Or cdlCFNoSizeSel
    Else
        .FontSize = RichTextBox1.SelFontSize
    End If
    If IsNull(RichTextBox1.SelBold) Or IsNull(RichTextBox1.SelItalic) Then
        .Flags = .Flags Or cdlCFNoStyleSel
    Else
        .FontBold = RichTextBox1.SelBold
        .FontItalic = RichTextBox1.SelItalic
    End If
    .CancelError = True
    .ShowFont
    If Err = 0 Then
        RichTextBox1.SelFontName = .FontName
        RichTextBox1.SelBold = .FontBold
        RichTextBox1.SelItalic = .FontItalic
        If (.Flags And cdlCFNoSizeSel) = 0 Then
            RichTextBox1.SelFontSize = .FontSize
        End If
        RichTextBox1.SelUnderline = .FontUnderline
        RichTextBox1.SelStrikeThru = .FontStrikethru
    End If
End With

The Printer Dialog

The CommonDialog control can display two distinct dialogs: the Print Setup dialog box that allows users to select a printer's attributes and the standard Print dialog that lets users select many options of a print job, such as which portion of the document should be printed (all, a page range, or the current selection), the number of copies, and so on. See Figures 12-4 and 12-5 for examples of these common dialog boxes.

Click to view at full size.

Figure 12-4. The Print common dialog box.

Click to view at full size.

Figure 12-5. The Print Setup common dialog box.

You decide which dialog box appears by setting the cdlPDPrintSetup bit in the Flags property. The complete list of bits that can be set in the Flags property is summarized in Table 12-3.

Table 12-3. Values for the Flags property for a printer common dialog box. Most of these bits are meaningless if you're showing a Print Setup dialog box (Flags = cdlPDPrintSetup).

Constant Description
cdlPDPrintSetup Display the Print Setup dialog box instead of the Print dialog box.
cdlPDNoWarning Prevent an error message if there isn't any default printer.
cdlPDHidePrintToFile Hide the Print To File check box.
cdlPDDisablePrintToFile Disable the Print To File check box.
cdlPDNoPageNums Disable the Pages option button.
cdlPDNoSelection Disable the Selection option button.
cdlPDPrintToFile The state of the Print To File check box. (Can be read upon exiting.)
cdlPDAllPages The state of the All Pages option button. (Can be read upon exiting.)
cdlPDPageNums The state of the Pages option button. (Can be read upon exiting)
cdlPDSelection The state of the Selection option button. (Can be read upon exiting.)
cdlPDCollate The state of the Collate check box. (Can be read upon exiting.)
cdlPDReturnDC The hDC property returns the device context of the selected printer.
cdlPDReturnIC The hDC property returns the information context of the selected printer.
cdlPDReturnDefault Return default printer name.
cdlPDUseDevModeCopies Set support for multiple copies.
cdlPDHelpButton Display the Help button.

When you're displaying a printer dialog box, the Min and Max properties are the minimum and maximum valid values for page numbers whereas FromPage and ToPage are the actual values displayed in the dialog box. You typically set the latter two properties upon entering and read them back upon exiting if the bit cdlPDPageNums is set. The Copies property reflects the number of copies entered by the user.

The PrinterDefault property determines whether the Visual Basic Printer object is automatically set to match the printer selected by the user. I recommend that you set this bit because it greatly simplifies subsequent print operations. If you don't set this bit, the only way you can retrieve information about the selected printer is through the Common Dialog's hDC property, which means that you need to perform your printing chores using API calls (not a simple thing to do).

When you're displaying a Print Setup dialog box, the Orientation property sets and returns the orientation selected for the printer job. (The settings can be 1cdlPortrait or 2cdlLandscape.) Neither the Orientation nor Copies properties are correctly set under Windows NT, however.

If you're showing a regular printer dialog box, you need to decide whether the Pages and the Selection option buttons should be enabled. For example, should a user want to print the contents of a TextBox control, you should enable the Selection option button only if the user actually selects a portion of text:

On Error Resume Next
With CommonDialog1
    ' Prepare to print using the Printer object.
    .PrinterDefault = True
    ' Disable printing to file and individual page printing.
    .Flags = cdlPDDisablePrintToFile Or cdlPDNoPageNums
    If Text1.SelLength = 0 Then
         ' Hide Selection button if there is no selected text.
        .Flags = .Flags Or cdlPDNoSelection
    Else 
        ' Else enable the Selection button and make it the default
        ' choice.
        .Flags = .Flags Or cdlPDSelection
    End If
    ' We need to know whether the user decided to print.
    .CancelError = True
    .ShowPrinter
    If Err = 0 Then
        If .Flags And cdlPDSelection Then
            Printer.Print Text1.SelText
        Else
            Printer.Print Text1.Text
        End If
    End If
End With

The FileOpen and FileSave Dialogs

The FileOpen and FileSave common dialog boxes are very similar, and in fact the Visual Basic documentation explains them together. While this is a reasonable approach, I have found that dealing with them jointly tends to hide the many subtle differences between these two dialog box types. For this reason, I decided to describe their common properties first and then focus on each type of dialog box in a separate section.

Properties in common

You can choose from an impressive number of ways to customize the appearance and behavior of the FileOpen and FileSave dialog boxes. For example, the DialogTitle property determines the caption of the common dialog box, and InitDir is the directory displayed when the dialog appears. When the dialog box is invoked, the FileName property contains the name of the prompted file. And when the dialog closes, it contains the name of the file selected by the user. The DefaultExt property can be assigned the default extension of a filename so that the control can automatically return a complete name in the FileName property even if the user doesn't type the extension. Alternatively, you can set and retrieve the base filename (that is, the name of the file without the extension) by using the FileTitle property.

You can define the file filters available to the user when browsing the contents of a directory. You do this by assigning the Filter property a string that contains (description, filter) pairs, with items separated by a pipe (|) character. For example, when working with graphic files, you can define three filters in the following way:

' You can specify multiple filters by using the semicolon as a delimiter.
CommonDialog1.Filter = "All Files|*.*|Bitmaps|*.bmp|Metafiles|*.wmf;*.emf"

You decide which filter is initially selected using the FilterIndex property:

' Display the Bitmaps filter. (Filters are one-based.)
CommonDialog1.FilterIndex = 2

The real difficulty in working with FileOpen and FileSave dialog boxes is that they support a lot of flags, and most flags aren't adequately documented in the Visual Basic manuals. In some cases, I had to resort to the Windows SDK documentation to understand what a given flag actually does. All the flags supported by FileOpen and FileSave common dialog boxes are summarized in Table 12-4.

Table 12-4. Values of the Flags property for a FileOpen or FileSave common dialog box. Note that a few bits make sense only with one of the two dialog boxes.

Constant Description
cdlOFNReadOnly The state of the Open As Read-Only check box (FileOpen only).
cdlOFNOverwritePrompt Show a message before overwriting existing files. (FileSave only.)
cdlOFNHideReadOnly Hide the Open As Read-Only check box. This bit should always be set in FileSave dialog boxes.
cdlOFNNoChangeDir Don't modify the current directory. (By default, a File dialog box changes current drive and directory to match the path of the file selected by the user.)
cdlOFNNoValidate Accept invalid characters in filenames. (Not recommended.)
cdlOFNAllowMultiselect Enable multiple file selection. (FileOpen only.)
cdlOFNExtensionDifferent The extension of the selected file is different from the value of the DefaultExt property. (To be tested upon exiting.)
cdlOFNPathMustExist Refuse filenames with invalid or nonexistent paths. (Highly recommended.)
cdlOFNFileMustExist Refuse to select files that don't exist. (FileOpen only.)
cdlOFNCreatePrompt If the selected file doesn't exist, ask whether a new file should be created. Automatically set cdlOFNFileMustExist and cdlOFNPathMustExist. (FileOpen only.)
cdlOFNShareAware Ignore network sharing errors. (Not recommended—use only if you're willing to solve sharing conflicts through code.)
cdlOFNNoReadOnlyReturn Refuse to select read-only files or files that reside in a write-protected directory.
cdlOFNExplorer Use a Windows Explorer-like interface in multiple-selection dialog boxes. (Multiple-selection FileOpen only; ignored in all other cases.)
cdlOFNLongNames This flag should enable long filenames in multiple-selection dialog boxes that use the Windows Explorer style. However, it turns out that these dialog boxes always support long filenames, so this feature appears to be useless. (Multiple-selection FileOpen only.)
cdlOFNNoDereferenceLinks Return the name and the path of the file selected by the user, even if this is a shortcut LNK file that points to another file. If this flag is omitted, when the user selects a LNK file the dialog box returns the name and path of the referenced file.
cdlOFNHelpButton Show the Help button.
cdlOFNNoLongNames Disallow long filenames.

When working with a FileOpen or a FileSave dialog box, you should always set the CancelError property to True because you need a way to find out whether the user canceled the file operation.

The FileSave dialog

Because the FileSave dialog box is the simpler of the two, I'll describe it first. Now you know enough to display a FileSave dialog box like the one shown in Figure 12-6. The next routine accepts a reference to a TextBox control and to a CommonDialog control: The routine uses the latter control to ask for a filename before it saves the contents of a TextBox control to the selected file. It returns the name of the file in the third argument:

' Returns False if the Save command has been canceled,
' True otherwise.
Function SaveTextControl(TB As Control, CD As CommonDialog, _
    Filename As String) As Boolean
    Dim filenum As Integer
    On Error GoTo ExitNow
    
    CD.Filter = "All files (*.*)|*.*|Text files|*.txt"
    CD.FilterIndex = 2
    CD.DefaultExt = "txt"
    CD.Flags = cdlOFNHideReadOnly Or cdlOFNPathMustExist Or _
        cdlOFNOverwritePrompt Or cdlOFNNoReadOnlyReturn
    CD.DialogTitle = "Select the destination file "
    CD.Filename = Filename
    ' Exit if user presses Cancel.
    CD.CancelError = True
    CD.ShowSave
    Filename = CD.Filename
    
    ' Write the control's contents.
    filenum = FreeFile()
    Open Filename For Output As #filenum
    Print #filenum, TB.Text;
    Close #filenum
    ' Signal success.
    SaveTextControl = True
ExitNow:

End Function

You can use the SaveTextControl routine as follows:

Dim Filename As String
If SaveTextControl(RichTextBox1, CommonDialog1, Filename) Then
    MsgBox "Text has been saved to file " & Filename
End If

Upon exiting a FileSave (and also a FileOpen) dialog box, you can test the cdlOFNExtensionDifferent bit of the Flags property, in case you need to know whether the selected file has an extension different from the one assigned to the DefaultExt property:

    If CD.Flags And cdlOFNExtensionDifferent Then
        ' Process nonstandard extensions here.
    End If

Figure 12-6. The FileSave common dialog box.

Don't forget to specify the cdlOFNHideReadOnly bit for FileSave dialog boxes: If you do forget, the Open As Read-Only check box will appear in the dialog box, which can confuse the user, who is saving a file, not opening it. Another convenient flag is cdlOFNNoReadOnlyReturn, which ensures that the file doesn't have the read-only attribute and therefore can be overwritten without raising an error.

The single-selection FileOpen dialog

The CommonDialog control supports both single- and multiple-selection FileOpen dialog boxes. The former type isn't substantially different from a FileSave dialog box, even though you usually specify different bits for the Flags property. Here's a reusable routine that loads the contents of a text file into a TextBox control:

' Returns False if the command has been canceled, True otherwise.
Function LoadTextControl(TB As Control, CD As CommonDialog, _
    Filename As String) As Boolean
    Dim filenum As Integer
    On Error GoTo ExitNow
    
    CD.Filter = "All files (*.*)|*.*|Text files|*.txt"
    CD.FilterIndex = 2
    CD.DefaultExt = "txt"
    CD.Flags = cdlOFNHideReadOnly Or cdlOFNFileMustExist Or _
        cdlOFNNoReadOnlyReturn
    CD.DialogTitle = "Select the source file "
    CD.Filename = Filename
    ' Exit if user presses Cancel.
    CD.CancelError = True
    CD.ShowOpen
    Filename = CD.Filename
    
    ' Read the file's contents into the control.
    filenum = FreeFile()
    Open Filename For Input As #filenum
    TB.Text = Input$(LOF(filenum), filenum)
    Close #filenum
    ' Signal success.
    LoadTextControl = True
ExitNow:
End Function

If you don't specify the cdlOFNHideReadOnly bit in the Flag property, the common dialog box includes the Open As Read-Only check box. To discover whether the user has clicked that check box, you test the Flags property upon exiting as follows:

    If CD.Flags And cdlOFNReadOnly Then
        ' The file has been opened in read-only mode.
        ' (For example, you should disable the File-Save command.)
    End If

The multiple-selection FileOpen dialog

Multiple-selection FileOpen dialog boxes are a bit more complex than single-selection dialog boxes. You specify that you want to open a multiple-selection file dialog box by setting the cdlOFNAllowMultiselect bit of the Flags property: All the files selected by the user will be concatenated in an individual string and then returned in the FileName property.

Because the user can select dozens or even hundreds of files, the returned string can be very long. By default, however, the FileOpen dialog box can deal only with returned strings of 256 characters or less: If the combined length of the file names selected by the user exceeds this limit, the control raises an error 20476 "Buffer too small." To circumvent this error, you can assign a higher value to the MaxFileSize property. For example, a value of 10 KB should suffice for most practical purposes:

CommonDialog1.MaxFileSize = 10240

To preserve compatibility with 16-bit programs, multiple-selection FileOpen dialogs return the lists of selected files using the space as a separator. Unfortunately, because the space is a valid character inside long filenames and therefore potentially confusing, all filenames are rendered in the old 8.3 MS-DOS format, and the dialog itself uses the outdated look visible in Figure 12-7. To work around this problem, you must specify the cdlOFNExplorer bit in the Flags property, which displays a modern Windows Explorer-like user interface and returns the list of selected files as long filenames separated by null characters. Note that the documentation is incorrect, and the cdlOFNLongNames flag can be safely omitted because Windows Explorer-like dialog boxes automatically support long filenames.

Figure 12-7. A multiple-selection FileOpen common dialog box without the cdlOFNExplorer flag uses an outdated Windows 3.x look.

Here's a reusable routine that asks the users for multiple files and then places all the filenames in a string array:

' Returns False if the command has been canceled, True otherwise.
Function SelectMultipleFiles(CD As CommonDialog, Filter As String, _
    Filenames() As String) As Boolean
    On Error GoTo ExitNow
    
    CD.Filter = "All files (*.*)|*.*|" & Filter
    CD.FilterIndex = 1
    CD.Flags = cdlOFNAllowMultiselect Or cdlOFNFileMustExist Or _
        cdlOFNExplorer
    CD.DialogTitle = "Select one or more files"
    CD.MaxFileSize = 10240
    CD.Filename = ""
    ' Exit if user presses Cancel.
    CD.CancelError = True
    CD.ShowOpen

    ' Parse the result to get filenames.
    Filenames() = Split(CD.Filename, vbNullChar)
    ' Signal success.
    SelectMultipleFiles = True
ExitNow:
End Function

After the user closes the dialog box, the Filename property might contain data in different formats, according to the number of files selected, for a couple of reasons.

The following code builds on the previously defined SelectMultipleFiles routine to find out which of these two cases occurred:

Dim Filenames() As String, i As Integer
If SelectMultipleFiles(CommonDialog1, "", Filenames()) Then
    If UBound(Filenames) = 0 Then
        ' The Filename property contained only one element.
        Print "Selected file: " & Filenames(0)
    Else
        ' The Filename property contained multiple elements.
        Print "Directory name: " & Filenames(0)
        For i = 1 To UBound(Filenames)
            Print "File #" & i & ": " & Filenames(i)
        Next
    End If
End If

Help Windows

You can use the CommonDialog control to display information from HLP files. In this case, no dialog box appears and only a few properties are used. You should assign the HelpFile property the filename and path, and the HelpCommand property an enumerated value that tells what you want to do with that file. Depending on which operation you're performing, you might need to assign a value to either the HelpKey or HelpContext property. Table 12-5 summarizes all the supported commands.

Table 12-5. All the possible values that can be assigned to the HelpCommand property when showing a help page.

Constant Description
cdlHelpContents Show help contents page.
cdlHelpContext Show the page whose context ID matches the value passed in the HelpContext property.
cdlHelpContextPopup Same as cdlHelpContext, but the help page appears in a pop-up window.
cdlHelpKey Show the page associated with the keyword passed in the HelpKey property.
cdlHelpPartialKey Same as cdlHelpKey, but also searches for partial matches.
cdlHelpCommandHelp Execute the help macro whose name has been assigned to the HelpKey property.
cdlHelpSetContents The help page pointed to by the HelpContext property becomes the content page for the specified help file.
cdlHelpForceFile Ensure that the help window is visible.
cdlHelpHelpOnHelp Show the Help on Help page.
cdlHelpQuit Close the help window.
cdlHelpIndex Show help contents page (same as cdlHelpContents).
cdlHelpSetIndex Set the current index for multi-index Help (same as cdlHelpSetContents).

The following code snippet shows how you can display the contents page associated with a help file:

' Show the contents page of DAO 3.5 help file.
With CommonDialog1
    ' Note: The path of this file may be different on your system.
    .HelpFile = "C:\WINNT\Help\Dao35.hlp"
    .HelpCommand = cdlHelpContents
    .ShowHelp
End With

You can also display a page associated with a keyword. If the keyword you provide in the HelpKey property doesn't match any particular page, the index of the help file is displayed instead:

With CommonDialog1
    .HelpFile = "C:\WINNT\Help\Dao35.hlp"
    .HelpCommand = cdlHelpKey
    .HelpKey = "BOF property"
    .ShowHelp
End With

You can also display a page associated with a given context ID, in which case you assign the cdlHelpContext constant to the HelpCommand property and the context ID to the HelpContext property. Of course, you must know which context ID corresponds to the particular page you're interested in, but this isn't a problem if you're the author of the help file. For more information about help context IDs, see the section "Showing Help" in Chapter 5.